package com.lwc.backendsinglestructure.aspect;


import cn.hutool.json.JSONUtil;
import com.lwc.backendsinglestructure.annotation.OperationLogInfo;
import com.lwc.backendsinglestructure.domain.entity.OperationLog;
import com.lwc.backendsinglestructure.mapper.OperationLogMapper;
import com.lwc.backendsinglestructure.utils.ThreadLocalUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.util.Map;

/**
 * 操作日志的切面
 * @author Rel
 * @date 2025/8/28 17:01
 */
@Component
@Aspect
public class OperationLogAspect {

    @Autowired
    private OperationLogMapper operationLogMapper;

    /**
     * 以自定义 @OperationLog 注解为切点
     */
    @Pointcut("@annotation(com.lwc.backendsinglestructure.annotation.OperationLogInfo)")
    public void operationLog() {
    }

    /**
     * 拦截操作日志
     */
    @Around("operationLog()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        OperationLog operationLog = new OperationLog();
        // 开始计时
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 1.首先获取注解上的参数
        MethodSignature signature = (MethodSignature) point.getSignature();
        OperationLogInfo operationLogInfo = signature.getMethod().getAnnotation(OperationLogInfo.class);
        if( operationLogInfo != null){
            operationLog.setApi(operationLogInfo.api());
            operationLog.setModule(operationLogInfo.module());
            operationLog.setTitle(operationLogInfo.title());
            operationLog.setMethod(operationLogInfo.method());
            operationLog.setDescription(operationLogInfo.description());
        }
        // 2.首先获取注解作用的方法上的参数
        String[] parameterNames = signature.getParameterNames();
        Object[] args = point.getArgs();
        // 3.判断参数有无 有就解析出来 没就不用解析
        if (parameterNames != null && parameterNames.length > 0){
            // 设置请求参数到操作日志表中
        }
        // 4.执行方法
        Object proceed = point.proceed();
        // 5.获取方法的返回值
        String result = JSONUtil.toJsonStr(proceed);
        operationLog.setResult(result);
        System.out.println("返回值：" + proceed);

        // 写入ip user-agent todo 此处通过拦截器获取
        Map<String, Object> hashMap = ThreadLocalUtil.get();
        String ip = (String)hashMap.get("ip");
        String browser = (String)hashMap.get("browser");
        operationLog.setIp(ip);
        operationLog.setBrowser(browser);

        // 结束计时
        stopWatch.stop();
        System.out.println("耗时：" + stopWatch.getTotalTimeMillis());
        operationLog.setCost_time(stopWatch.getTotalTimeMillis());

        // 入库
        operationLogMapper.insert(operationLog);
        return null;
    }



}
